package com.songwo.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.MessagingException;
import java.io.File;
import java.util.Map;

/**
 * 邮件工具类
 *
 * @author zhongzheng
 */
@Component
public class MailUtils {

    private static final boolean IS_HTML = true;
    private static final boolean IS_MULTIPART = true;
    private static final String ENCODING = "UTF-8";

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private TemplateEngine templateEngine;

    @Value("${sw.mail.from}")
    private String from;

    /**
     * 发送包含图片的邮件
     *
     * @param recipients        收件方
     * @param cc                抄送
     * @param subject           标题
     * @param templateName      模版名称
     * @param datas             数据
     * @param attachments       附件
     * @param imageResourceName 图片名称
     * @param imageBytes        图片数据
     * @param imageContentType  图片类型
     */
    public void sendMailWithInlineImage(String[] recipients, String[] cc, String subject, String templateName, Map<String, Object> datas, String[] attachments
            , String imageResourceName, byte[] imageBytes, String imageContentType) {

        final InputStreamSource imageSource = new ByteArrayResource(imageBytes);

        MimeMessagePreparator mimeMessagePreparator = mimeMessage -> {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, IS_MULTIPART, ENCODING);
            composeMessageHeader(recipients, cc, subject, attachments, messageHelper);
            messageHelper.setText(buildMessage(templateName, datas), IS_HTML);
            messageHelper.addInline(imageResourceName, imageSource, imageContentType);
        };

        mailSender.send(mimeMessagePreparator);
    }

    /**
     * 发送包含图片的邮件
     *
     * @param recipients        收件方
     * @param cc                抄送
     * @param subject           标题
     * @param templateName      模版名称
     * @param datas             数据
     * @param attachments       附件
     * @param imageResourceName 图片名称
     * @param imageFileName     图片名称
     */
    public void sendMailWithInlineImage(String[] recipients, String[] cc, String subject, String templateName, Map<String, Object> datas, String[] attachments
            , String imageResourceName, String imageFileName) {

        final FileSystemResource image = new FileSystemResource(new File(imageFileName));

        MimeMessagePreparator mimeMessagePreparator = mimeMessage -> {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, IS_MULTIPART, ENCODING);
            composeMessageHeader(recipients, cc, subject, attachments, messageHelper);
            messageHelper.setText(buildMessage(templateName, datas), IS_HTML);
            messageHelper.addInline(imageResourceName, image);
        };

        mailSender.send(mimeMessagePreparator);
    }

    /**
     * 发送邮件
     *
     * @param recipients   收件方
     * @param cc           抄送
     * @param subject      标题
     * @param templateName 模版名称
     * @param datas        数据
     * @param attachments  附件
     */
    public void sendMail(String[] recipients, String[] cc, String subject, String templateName, Map<String, Object> datas, String[] attachments) {
        MimeMessagePreparator mimeMessagePreparator = mimeMessage -> {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, IS_MULTIPART, ENCODING);
            composeMessageHeader(recipients, cc, subject, attachments, messageHelper);
            messageHelper.setText(buildMessage(templateName, datas), IS_HTML);
        };

        mailSender.send(mimeMessagePreparator);
    }

    /**
     * 发送纯文字邮件
     *
     * @param recipients  收件方
     * @param cc          抄送
     * @param subject     标题
     * @param message     消息内容
     * @param attachments 附件
     */
    public void sendMailText(String[] recipients, String[] cc, String subject, String message, String[] attachments) {
        MimeMessagePreparator mimeMessagePreparator = mimeMessage -> {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, IS_MULTIPART, ENCODING);
            composeMessageHeader(recipients, cc, subject, attachments, messageHelper);
            messageHelper.setText(message, !IS_HTML);
        };

        mailSender.send(mimeMessagePreparator);
    }


    /**
     * 拼装邮件头部
     *
     * @param recipients    收件方
     * @param cc            抄送
     * @param subject       标题
     * @param attachments   附件
     * @param messageHelper
     * @throws MessagingException
     */
    private void composeMessageHeader(String[] recipients, String[] cc, String subject, String[] attachments,
                                      MimeMessageHelper messageHelper) throws MessagingException {
        messageHelper.setFrom(from);
        messageHelper.setTo(recipients);
        messageHelper.setCc(cc);
        messageHelper.setSubject(subject);
        if (attachments != null) {
            for (String filename : attachments) {
                FileSystemResource file = new FileSystemResource(filename);
                messageHelper.addAttachment(file.getFilename(), file);
            }
        }
    }

    /**
     * 生成邮件内容
     *
     * @param templateName 模版名称
     * @param datas        数据
     * @return
     */
    private String buildMessage(String templateName, Map<String, Object> datas) {
        Context context = new Context();
        for (Map.Entry<String, Object> entry : datas.entrySet()) {
            context.setVariable(entry.getKey(), entry.getValue());
        }
        return templateEngine.process(templateName, context);
    }
}